#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <regex>
#include <sstream>
#include <stack>

#include "PocoJsonPath.h"

#define LOGIC_OPR_NO    0   // None
#define LOGIC_OPR_GT    1   // Greate
#define LOGIC_OPR_LT    2   // Little
#define LOGIC_OPR_EQ    3   // Equale
#define LOGIC_OPR_GE    4   // Greate Equale
#define LOGIC_OPR_LE    5   // Little Equale
#define LOGIC_OPR_NE    6   // Not Equale

// 定义一些常量和类型
const int MAX_PATH_LENGTH = 256;
const int MAX_MEMBERS = 100;

static std::string trim(const std::string& str) 
{
    // 查找第一个非空格字符的位置
    size_t start = str.find_first_not_of(" ");
    // 若全为空格，返回空字符串
    if (start == std::string::npos) return "";

    // 查找最后一个非空格字符的位置
    size_t end = str.find_last_not_of(" ");

    // 截取子串
    return str.substr(start, end - start + 1);
}

// 转换 UTF-8 字符串到小写
static std::string toLower(const std::string& str) {
    std::string result = str;
    std::transform(result.begin(), result.end(), result.begin(),
                   [](unsigned char c) { return std::tolower(c); });
    return result;
}

static std::list<std::string> split(const std::string& str, char delimiter) {
    std::list<std::string> tokens;
    std::stringstream ss(str);
    std::string token;

    while (std::getline(ss, token, delimiter)) {
        if (!token.empty())  // 可选：忽略空字符串
            tokens.push_back(token);
    }

    return tokens;
}

JsonPathContext::JsonPathContext(std::unique_ptr<IJsonPathValueSystem> system) : system(std::move(system)) 
{
    
}

void JsonPathContext::SelectTo(const Poco::Dynamic::Var& obj, const std::string& expr, JsonPathResultAccumulator output) 
{
    std::string normalizedExpr = Normalize(expr);
    if (!normalizedExpr.empty() && normalizedExpr[0] == '$') {
        if (normalizedExpr.length() >= 2 && normalizedExpr[1] == ';') {
            normalizedExpr = normalizedExpr.substr(2);
        } else {
            normalizedExpr = normalizedExpr.substr(1);
        }
    }
    Trace(normalizedExpr, obj, "$", output);
}

std::string JsonPathContext::Normalize(const std::string& expr) 
{
    std::string result = expr;
    std::regex re1(R"([\['](\??\(.*?\))[\]'])");
    std::regex re2(R"('?\.'?|\['?)");
    std::regex re3(R"(;;;|;;)");
    std::regex re4(R"(;$|'?\]|'$)");
    std::regex re5(R"(#([0-9]+))");

    std::vector<std::string> subx;
    // 手动处理 re1 的替换
    std::string newResult;
    auto words_begin = std::sregex_iterator(result.begin(), result.end(), re1);
    auto words_end = std::sregex_iterator();
    size_t lastPos = 0;
    for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
        std::smatch match = *i;
        subx.push_back(match[1].str());
        newResult += result.substr(lastPos, match.position() - lastPos);
        newResult += "[#" + std::to_string(subx.size() - 1) + "]";
        lastPos = match.position() + match.length();
    }
    newResult += result.substr(lastPos);
    result = newResult;

    result = std::regex_replace(result, re2, ";");
    result = std::regex_replace(result, re3, ";..;");
    result = std::regex_replace(result, re4, "");

    // 手动处理 re5 的替换
    newResult.clear();
    words_begin = std::sregex_iterator(result.begin(), result.end(), re5);
    lastPos = 0;
    for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
        std::smatch match = *i;
        int index = std::stoi(match[1].str());
        newResult += result.substr(lastPos, match.position() - lastPos);
        newResult += subx[index];
        lastPos = match.position() + match.length();
    }
    newResult += result.substr(lastPos);
    result = newResult;

    std::cout << "Normalize " << result << std::endl;
    return result;
}

double JsonPathContext::evaluateExpression(const std::string& script, const Poco::Dynamic::Var& value) 
{
    std::stack<double> values;
    std::stack<char> operators;

    auto precedence = [](char op) {
        if (op == '+' || op == '-')
            return 1;
        if (op == '*' || op == '/')
            return 2;
        return 0;
    };

    auto applyOp = [](double a, double b, char op) {
        switch (op) {
        case '+': return a + b;
        case '-': return a - b;
        case '*': return a * b;
        case '/': return a / b;
        }
        return 0.0;
    };

    for (size_t i = 0; i < script.length(); ++i) {
        if (script[i] == ' ')
            continue;

        if (std::isdigit(script[i])) {
            double val = 0;
            while (i < script.length() && std::isdigit(script[i])) {
                val = (val * 10) + (script[i] - '0');
                ++i;
            }
            --i;
            values.push(val);
        } else if (script[i] == '@') {
            ++i; // Skip "@" char
            if (script[i] != '.') {
                return -1;
            }
            ++i; // Skip "." char
            std::string member;
            while (std::isalnum(script[i])) {
                member += script[i];
                ++i;
            }
            if (system->IsArray(value) && (member == "length")) {
                Poco::JSON::Array::Ptr arr = value.extract<Poco::JSON::Array::Ptr>();
                values.push(arr->size());
            }
//            ++i; // Skip ".length" part as we already handled it
            while (i < script.length() && script[i] != '+' && script[i] != '-' && script[i] != '*' && script[i] != '/')
                ++i;
            --i;
        } else if (script[i] == '(') {
            operators.push(script[i]);
        } else if (script[i] == ')') {
            while (!operators.empty() && operators.top() != '(') {
                double val2 = values.top();
                values.pop();
                double val1 = values.top();
                values.pop();
                char op = operators.top();
                operators.pop();
                values.push(applyOp(val1, val2, op));
            }
            if (!operators.empty())
                operators.pop();
        } else {
            while (!operators.empty() && precedence(operators.top()) >= precedence(script[i])) {
                double val2 = values.top();
                values.pop();
                double val1 = values.top();
                values.pop();
                char op = operators.top();
                operators.pop();
                values.push(applyOp(val1, val2, op));
            }
            operators.push(script[i]);
        }
    }

    while (!operators.empty()) {
        double val2 = values.top();
        values.pop();
        double val1 = values.top();
        values.pop();
        char op = operators.top();
        operators.pop();
        values.push(applyOp(val1, val2, op));
    }

    return values.top();
}

bool JsonPathContext::evaluateLogicalExpression(const std::string& script, const Poco::Dynamic::Var& value) 
{
    std::stack<bool> values;
    std::stack<char> operators;

    auto precedence = [](char op) {
        if (op == '&')
            return 2;
        if (op == '|')
            return 1;
        return 0;
    };

    auto applyOp = [](bool a, bool b, char op) {
        switch (op) {
            case '&': return a && b;
            case '|': return a || b;
        }
        return false;
    };

    size_t i = 0;
    while (i < script.length()) {
        if (script[i] == ' ') {
            ++i;
            continue;
        }

        if (script[i] == '(') {
            operators.push(script[i]);
            ++i;
        } else if (script[i] == ')') {
            while (!operators.empty() && operators.top() != '(') {
                bool val2 = values.top();
                values.pop();
                bool val1 = values.top();
                values.pop();
                char op = operators.top();
                operators.pop();
                values.push(applyOp(val1, val2, op));
            }
            if (!operators.empty())
                operators.pop();
            ++i;
        } else if (script[i] == '&' || script[i] == '|') {
            while (!operators.empty() && precedence(operators.top()) >= precedence(script[i])) {
                bool val2 = values.top();
                values.pop();
                bool val1 = values.top();
                values.pop();
                char op = operators.top();
                operators.pop();
                values.push(applyOp(val1, val2, op));
            }
            operators.push(script[i]);
            i += 2; // Skip the second character of && or ||
        } else {
            size_t start = i;
            while (i < script.length() && script[i] != '(' && script[i] != ')' && script[i] != '&' && script[i] != '|')
                ++i;
            std::string subExpr = script.substr(start, i - start);
            values.push(evaluateFilterExpression(subExpr, value));
        }
    }

    while (!operators.empty()) {
        bool val2 = values.top();
        values.pop();
        bool val1 = values.top();
        values.pop();
        char op = operators.top();
        operators.pop();
        values.push(applyOp(val1, val2, op));
    }

    return values.top();
}

bool JsonPathContext::evaluateFilterExpression(const std::string& script, const Poco::Dynamic::Var& value) 
{
    if (script.find("&&") != std::string::npos || script.find("||") != std::string::npos) {
        return evaluateLogicalExpression(script, value);
    }

    std::string leftExpr, rightExpr;
    char op = LOGIC_OPR_NO;
    for (size_t i = 0; i < script.length(); ++i) {
        if (script[i] == '>' || script[i] == '<' || script[i] == '=' || script[i] == '!') {
            leftExpr = script.substr(0, i);
            if (script[i + 1] == '=') {
                op = script[i] == '=' ? LOGIC_OPR_EQ : script[i] == '!' ? LOGIC_OPR_NE : script[i] == '>' ? LOGIC_OPR_GE : script[i] == '<' ? LOGIC_OPR_LE : LOGIC_OPR_NO;
                rightExpr = script.substr(i + 2);
                ++i;
            } else {
                op = script[i] == '=' ? LOGIC_OPR_EQ : script[i] == '!' ? LOGIC_OPR_NE : script[i] == '>' ? LOGIC_OPR_GE : script[i] == '<' ? LOGIC_OPR_LE : LOGIC_OPR_NO;
                rightExpr = script.substr(i + 1);
            }
            leftExpr = trim(leftExpr);
            rightExpr = trim(rightExpr);

            break;
        }
    }

    if (op == LOGIC_OPR_NO) {
        leftExpr = script;
        leftExpr = trim(leftExpr);
        if (leftExpr[0] == '@' && leftExpr[1] == '.') {
            if (system->HasMember(value, leftExpr.substr(2)) ) {
                return true;
            }
        } else {

        }
        return false;
    }

    auto getValue = [this, &value](const std::string& expr) {
        if (expr.substr(0, 2) == "@.") {
            std::string key = expr.substr(2);
            if (system->IsObject(value)) {
                Poco::JSON::Object::Ptr obj = value.extract<Poco::JSON::Object::Ptr>();
                if (obj->has(key)) {
                    return obj->get(key);
                } else {
                    return Poco::Dynamic::Var();
                }
            }
        }
        // 去除引号
        if (expr.front() == '"' && expr.back() == '"') {
            return Poco::Dynamic::Var(expr.substr(1, expr.length() - 2));
        } else if (expr.front() == '\'' && expr.back() == '\'') {
            return Poco::Dynamic::Var(expr.substr(1, expr.length() - 2));
        } else if (toLower(expr) == "true") {
            return Poco::Dynamic::Var(true);
        } else if (toLower(expr) == "false") {
            return Poco::Dynamic::Var(false);
        } else {
            try {
                return Poco::Dynamic::Var(std::stod(expr));
            } catch (...) {
                return Poco::Dynamic::Var(expr);
            }
        }
    };

    auto leftVal = getValue(leftExpr);
    auto rightVal = getValue(rightExpr);

    if (leftVal.isEmpty()) {
        return false;
    } else if (leftVal.isNumeric()) {
    } else if (leftVal.isString()) {
    }
    if (rightVal.isEmpty()) {
        return false;
    } else if (rightVal.isNumeric()) {
    } else if (rightVal.isString()) {
    }
    if (leftVal.isNumeric() && rightVal.isNumeric()) {
        double left = leftVal.convert<double>();
        double right = rightVal.convert<double>();
        switch (op) {
        case LOGIC_OPR_GT: return left > right;
        case LOGIC_OPR_LT: return left < right;
        case LOGIC_OPR_GE: return left >= right;
        case LOGIC_OPR_LE: return left <= right;
        case LOGIC_OPR_EQ: return std::abs(left - right) < 1e-9;
        case LOGIC_OPR_NE: return std::abs(left - right) >= 1e-9;
        default: return false;
        }
    } else if (leftVal.isString() && rightVal.isString()) {
        std::string left = leftVal.toString();
        std::string right = rightVal.toString();
        switch (op) {
        case LOGIC_OPR_EQ: return left == right;
        case LOGIC_OPR_NE: return left != right;
        default: return left != right;
        }
    } else if (leftVal.isBoolean() && rightVal.isBoolean()) {
        bool left = leftVal.convert<bool>();
        bool right = rightVal.convert<bool>();
        switch (op) {
        case LOGIC_OPR_EQ: return left == right;
        case LOGIC_OPR_NE: return left != right;
        default: return left != right;
        }
    }

    return false;
}

void JsonPathContext::Trace(const std::string& expr, const Poco::Dynamic::Var& value, const std::string& path, JsonPathResultAccumulator output) 
{
    if (expr.empty()) {
        std::vector<std::string> indicies;
        std::string currentPath = path;
        size_t pos = 0;
        while ((pos = currentPath.find(';')) != std::string::npos) {
            indicies.push_back(currentPath.substr(0, pos));
            currentPath.erase(0, pos + 1);
        }
        indicies.push_back(currentPath);
        output(value, indicies);
        return;
    }

    ssize_t i = expr.find(';');
    std::string atom = i != std::string::npos ? expr.substr(0, i) : expr;
    std::string tail = i != std::string::npos ? expr.substr(i + 1) : "";

    if (system->HasMember(value, atom)) {
        Trace(tail, system->GetMemberValue(value, atom), path + ";" + atom, output);
    } else if (atom == "*") {
        Walk(atom, tail, value, path, [this, &output](const std::string& member, const std::string& loc, const std::string& expr, const Poco::Dynamic::Var& value, const std::string& path) {
            Trace(member + ";" + expr, value, path, output);
        });
    } else if (atom == "..") {
        Trace(tail, value, path, output);
        Walk(atom, tail, value, path, [this, &output](const std::string& member, const std::string& loc, const std::string& expr, const Poco::Dynamic::Var& value, const std::string& path) {
            Poco::Dynamic::Var result = system->GetMemberValue(value, member);
            if (!result.isEmpty() &&!system->IsPrimitive(result)) {
                Trace("..;" + expr, result, path + ";" + member, output);
            }
        });
    } else if (atom.length() > 2 && atom[0] == '(' && atom[atom.length() - 1] == ')') { // [(exp)]
        std::string script = atom.substr(1, atom.length() - 2);
        double result = evaluateExpression(script, value);
        if (system->IsArray(value)) {
            Poco::JSON::Array::Ptr arr = value.extract<Poco::JSON::Array::Ptr>();
            size_t index = static_cast<size_t>(result);
            if ((index < arr->size()) && (index >= 0)) {
                Poco::Dynamic::Var element = arr->get(index);
                Trace(tail, element, path + ";" + std::to_string(index), output);
            }
        }
    } else if (atom.length() > 3 && atom[0] == '?' && atom[1] == '(' && atom[atom.length() - 1] == ')') { // [?(exp)]
        Walk(atom, tail, value, path, [this, &output](const std::string& member, const std::string& loc, const std::string& expr, const Poco::Dynamic::Var& value, const std::string& path) {
            Poco::Dynamic::Var result = system->GetMemberValue(value, member);
            std::string filterScript = loc.substr(2, loc.length() - 3);
            if (!result.isEmpty() && evaluateFilterExpression(filterScript, result)) {
                Trace(member + ";" + expr, value, path, output);
            }
        });
    } else if (std::regex_match(atom, std::regex("^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$"))) { // [start:end:step] Phyton slice syntax
        // 实现切片逻辑
        if (system->IsArray(value)) {
            Poco::JSON::Array::Ptr arr = value.extract<Poco::JSON::Array::Ptr>();
            size_t length = arr->size();
            std::vector<std::string> parts;
            std::stringstream ss(atom);
            std::string part;
            while (std::getline(ss, part, ':')) {
                parts.push_back(part);
            }

            int start = parts.size() > 0 && !parts[0].empty() ? std::stoi(parts[0]) : 0;
            int end = parts.size() > 1 && !parts[1].empty() ? std::stoi(parts[1]) : static_cast<int>(length);
            int step = parts.size() > 2 && !parts[2].empty() ? std::stoi(parts[2]) : 1;
            start = (start < 0) ? std::max(0, start + static_cast<int>(length)) : std::min(static_cast<int>(length), start);
            end = (end < 0) ? std::max(0, end + static_cast<int>(length)) : std::min(static_cast<int>(length), end);
            for (int i = start; i < end; i += step) {
                Trace(std::to_string(i) + ";" + tail, value, path, output);
            }
        }
    } else if (atom.find(',') != std::string::npos) { // [name1,name2,...]
        size_t start = 0;
        size_t end = atom.find(',');
        while (end != std::string::npos) {
            Trace(atom.substr(start, end - start) + ";" + tail, value, path, output);
            start = end + 1;
            end = atom.find(',', start);
        }
        Trace(atom.substr(start) + ";" + tail, value, path, output);
    } else {
    }
}

void JsonPathContext::Walk(const std::string& loc, const std::string& expr, const Poco::Dynamic::Var& value, const std::string& path, std::function<void(const std::string&, const std::string&, const std::string&, const Poco::Dynamic::Var&, const std::string&)> callback) 
{
    if (system->IsPrimitive(value)) {
        return;
    } else if (system->IsArray(value)) {
        Poco::JSON::Array::Ptr arr = value.extract<Poco::JSON::Array::Ptr>();
        for (size_t i = 0; i < arr->size(); ++i) {
            callback(std::to_string(i), loc, expr, value, path);
        }
    } else if (system->IsObject(value)) {
        Poco::JSON::Object::Ptr obj = value.extract<Poco::JSON::Object::Ptr>();
        for (const auto& kv : *obj) {
            callback(kv.first, loc, expr, value, path);
        }
    }
}

bool PocoJsonValueSystem::HasMember(const Poco::Dynamic::Var& value, const std::string& member) const
{
    if (IsPrimitive(value)) {
        return false;
    } else if (IsObject(value)) {
        Poco::JSON::Object::Ptr obj = value.extract<Poco::JSON::Object::Ptr>();
        return obj->has(member);
    } else if (IsArray(value)) {
        Poco::JSON::Array::Ptr arr = value.extract<Poco::JSON::Array::Ptr>();
        // 检查 member 是否全是数字字符
        if (member.find_first_not_of("0123456789") == std::string::npos) {
            try {
                size_t index = std::stoul(member);
                return index < arr->size();
            } catch (...) {
                return false;
            }
        }
        return false;
    }
    return false;
}

Poco::Dynamic::Var PocoJsonValueSystem::GetMemberValue(const Poco::Dynamic::Var& value, const std::string& member) const
{
    if (IsObject(value)) {
        Poco::JSON::Object::Ptr obj = value.extract<Poco::JSON::Object::Ptr>();
        if (obj->has(member)) {
            return obj->get(member);
        }
    } else if (IsArray(value)) {
        Poco::JSON::Array::Ptr arr = value.extract<Poco::JSON::Array::Ptr>();
        if (member.find_first_not_of("0123456789") == std::string::npos) {
            try {
                size_t index = std::stoul(member);
                if (index < arr->size()) {
                    return arr->get(index);
                }
            } catch (...) {
                return Poco::Dynamic::Var();
            }
        }
    }
    return Poco::Dynamic::Var();
}

std::vector<std::string> PocoJsonValueSystem::GetMembers(const Poco::Dynamic::Var& value) const 
{
    std::vector<std::string> members;
    if (IsObject(value)) {
        Poco::JSON::Object::Ptr obj = value.extract<Poco::JSON::Object::Ptr>();
        for (const auto& kv : *obj) {
            members.push_back(kv.first);
        }
    } else if (IsArray(value)) {
        Poco::JSON::Array::Ptr arr = value.extract<Poco::JSON::Array::Ptr>();
        for (size_t i = 0; i < arr->size(); ++i) {
            members.push_back(std::to_string(i));
        }
    }
    return members;
}

bool PocoJsonValueSystem::IsObject(const Poco::Dynamic::Var& value) const 
{
    return value.type() == typeid(Poco::JSON::Object::Ptr);
}

bool PocoJsonValueSystem::IsArray(const Poco::Dynamic::Var& value) const 
{
    return value.type() == typeid(Poco::JSON::Array::Ptr);
}

bool PocoJsonValueSystem::IsPrimitive(const Poco::Dynamic::Var& value) const 
{
    return value.isInteger() || value.isString() || value.isBoolean() || value.isNumeric();
}

// 模拟 AsBracketNotation 函数
static std::string AsBracketNotation(const std::vector<std::string>& indicies) 
{
    std::string result = "$";
    for (const auto& index : indicies) {
        if (index == "$") continue;
        if (std::regex_match(index, std::regex("^[0-9*]+$"))) {
            result += "[" + index + "]";
        } else {
            result += "['" + index + "']";
        }
    }
    return result;
}

static std::string JsonFullPath(const std::vector<std::string>& indicies)
{
    std::string result = "";
    for (const auto& index : indicies) {
        if (index == "$") continue;
        if (std::regex_match(index, std::regex("^[0-9*]+$"))) {
            result += "/" + index;
        } else {
            result += "/" + index;
        }
    }
    return result;
}

void ListAccumulator::Put(const Poco::Dynamic::Var& value, const std::vector<std::string>& indicies) 
{
    JsonPathNode node;
    node.value = value;
    node.path = AsBracketNotation(indicies);
    node.path2 = JsonFullPath(indicies);
    nodes.push_back(node);
}

const std::vector<JsonPathNode>& ListAccumulator::GetNodes() const 
{
    return nodes;
}

ListAccumulator PocoJsonPath(const std::string &jsonStr, const std::string &jsonpath)
{
    Poco::JSON::Parser parser;
    Poco::Dynamic::Var jsonVar = parser.parse(jsonStr);

    auto system = make_unique<PocoJsonValueSystem>();
    JsonPathContext context(std::move(system));

    ListAccumulator acc;

    context.SelectTo(jsonVar, jsonpath, [&acc](const Poco::Dynamic::Var& value, const std::vector<std::string>& indicies) {
        acc.Put(value, indicies);
    });

    return acc;
}

ListAccumulator PocoJsonPath(const Poco::Dynamic::Var &jsonVar, const std::string &jsonpath)
{
    auto system = make_unique<PocoJsonValueSystem>();
    JsonPathContext context(std::move(system));

    ListAccumulator acc;

    context.SelectTo(jsonVar, jsonpath, [&acc](const Poco::Dynamic::Var& value, const std::vector<std::string>& indicies) {
        acc.Put(value, indicies);
    });

    return acc;
}

void JsonPathSet(Poco::Dynamic::Var &jsonVar, const std::string &jsonpath, const Poco::Dynamic::Var &value)
{
    auto system = make_unique<PocoJsonValueSystem>();
    JsonPathContext context(std::move(system));

    ListAccumulator acc;
    Poco::JSON::Object::Ptr object_ptr;
    Poco::JSON::Array::Ptr array_ptr;

    context.SelectTo(jsonVar, jsonpath, [&acc](const Poco::Dynamic::Var& value, const std::vector<std::string>& indicies) {
        acc.Put(value, indicies);
    });

    std::cout << "Set: " << std::endl;
    const auto& nodes = acc.GetNodes();
    for (const auto& node : nodes) {
        std::cout << "Nodes: " << node.path << "  " << node.path2 << " = " << node.value.toString() << std::endl;
        std::list<std::string> paths = split(node.path2, '/');

        object_ptr = jsonVar.extract<Poco::JSON::Object::Ptr>();
        for (std::list<std::string>::iterator it = paths.begin(); it != paths.end(); ++it) {
            if (object_ptr->isArray(*it)) {
                array_ptr = object_ptr->getArray(*it);
                it++;it++;
                if ((it) == paths.end()) {
                    it--;
                    array_ptr->set(atoi(it->c_str()), value);
                    break;
                } else {
                    it--;it--;
                }
            } else {
                object_ptr = object_ptr->getObject(*it);
                it++;it++;
                if ((it) == paths.end()) {
                    it--;
                    object_ptr->set(*it, value);
                    break;
                } else {
                    it--;it--;
                }
            }
        }
    }
}

void JsonPathAdd(Poco::Dynamic::Var &jsonVar, const std::string &jsonpath, const std::string &key, const Poco::Dynamic::Var &value)
{
    auto system = make_unique<PocoJsonValueSystem>();
    JsonPathContext context(std::move(system));

    ListAccumulator acc;
    Poco::JSON::Object::Ptr object_ptr;
    Poco::JSON::Array::Ptr array_ptr;

    context.SelectTo(jsonVar, jsonpath, [&acc](const Poco::Dynamic::Var& value, const std::vector<std::string>& indicies) {
        acc.Put(value, indicies);
    });

    std::cout << "Add: " << std::endl;
    const auto& nodes = acc.GetNodes();
    for (const auto& node : nodes) {
        std::cout << "Nodes: " << node.path << "  " << node.path2 << " = " << node.value.toString() << std::endl;
        std::list<std::string> paths = split(node.path2, '/');

        object_ptr = jsonVar.extract<Poco::JSON::Object::Ptr>();
        for (std::list<std::string>::iterator it = paths.begin(); it != paths.end(); ++it) {
            if (object_ptr->isArray(*it)) {
                array_ptr = object_ptr->getArray(*it);
                it++;
                if ((it) == paths.end()) {
                    array_ptr->add(value);
                    break;
                } else {
                    it--;
                }
            } else {
                object_ptr = object_ptr->getObject(*it);
                it++;
                if ((it) == paths.end()) {
                    object_ptr->set(key, value);
                    break;
                } else {
                    it--;
                }
            }
        }
    }
}

void JsonPathDel(Poco::Dynamic::Var &jsonVar, const std::string &jsonpath)
{
    auto system = make_unique<PocoJsonValueSystem>();
    JsonPathContext context(std::move(system));

    ListAccumulator acc;
    Poco::JSON::Object::Ptr object_ptr;
    Poco::JSON::Array::Ptr array_ptr;

    context.SelectTo(jsonVar, jsonpath, [&acc](const Poco::Dynamic::Var& value, const std::vector<std::string>& indicies) {
        acc.Put(value, indicies);
    });

    std::cout << "Del: " << std::endl;
    std::vector<JsonPathNode> nodes = acc.GetNodes();
    for (std::vector<JsonPathNode>::reverse_iterator rit = nodes.rbegin(); rit != nodes.rend(); rit++) {
        const JsonPathNode node = *rit;
        std::cout << "Nodes: " << node.path << "  " << node.path2 << " = " << node.value.toString() << std::endl;
        std::list<std::string> paths = split(node.path2, '/');

        object_ptr = jsonVar.extract<Poco::JSON::Object::Ptr>();
        for (std::list<std::string>::iterator it = paths.begin(); it != paths.end(); ++it) {
            if (object_ptr->isArray(*it)) {
                array_ptr = object_ptr->getArray(*it);
                it++;it++;
                if ((it) == paths.end()) {
                    it--;
                    array_ptr->remove(atoi(it->c_str()));
                    break;
                } else {
                    it--;it--;
                }
            } else {
                object_ptr = object_ptr->getObject(*it);
                it++;it++;
                if ((it) == paths.end()) {
                    it--;
                    object_ptr->remove(*it);
                    break;
                } else {
                    it--;it--;
                }
            }
        }
    }
}
